﻿namespace HostTracker.Azure.Management

open System
open System.Net
open System.ServiceModel
open System.ServiceModel.Web
open System.Runtime.Serialization

type CloudSuccessResponce<'T> = {
    httpCode: int
    requestId: string
    data: 'T
}

type CloudFailResponce<'T> = {
    //e: WebException
    data: 'T
}

type CloudResponce<'T, 'Error> = 
    | Success of CloudSuccessResponce<'T> 
    | Fail of CloudFailResponce<'Error>
    
(*
<?xml version="1.0" encoding="utf-8"?> 
<Error> 
  <Code>error-code</Code> 
  <Message>detailed-error-message</Message> 
  <Severity>severity-level</Severity> 
  <State>state-information</State> 
</Error>
*)
/// <summary>
///<para>Represent error responce for Azure SQL management request</para>
///<para>See http://msdn.microsoft.com/en-us/library/windowsazure/gg715279.aspx</para>
///</summary>
[<DataContract(Name="Error", Namespace = "http://schemas.microsoft.com/sqlazure/2010/12/")>]
type SqlManagementError() =     
    let mutable code = 0
    let mutable message = ""
    let mutable severity = ""
    let mutable state =""
    [<DataMember(Name="Code", Order = 1)>]
    member x.Code with get () = code and set v = code <- v
    [<DataMember(Name="Message", Order = 2)>]
    member x.Message with get () = message and set v = message <- v
    [<DataMember(Name="Severity", Order = 3)>]
    member x.Severity with get () = severity and set v = severity <- v
    [<DataMember(Name="State", Order = 4)>]
    member x.State with get () = state and set v = state <- v

(*
<?xml version="1.0" encoding="utf-8"?>
<Error>
  <Code>string-code</Code>
  <Message>detailed-error-message</Message>
</Error>
*)
/// <summary>
///<para>Represent error responce for Azure Service management request</para>
///<para>See http://msdn.microsoft.com/en-us/library/windowsazure/ee460801.aspx
///</summary>
[<DataContract(Name="Error", Namespace="http://schemas.microsoft.com/windowsazure")>]
type ServiceManagementError() =
    let mutable code = ""
    let mutable message = ""
    [<DataMember(Name = "Code", Order = 1)>]
    member x.Code with get () = code and set v = code <- v
    [<DataMember(Name = "Message", Order = 2)>]
    member x.Message with get () = message and set v = message <- v

module CloudErrorProcessing = 
    let failResult<'T, 'Error> (e: WebException) : CloudResponce<'T, 'Error> =
        use stream = (e.Response :?> HttpWebResponse).GetResponseStream()
        let serializer = DataContractSerializer(typeof<'Error>) //XmlSerializer(typeof<Error>)      
        { data = serializer.ReadObject(stream) :?> 'Error } |> Fail
    let failControll<'T, 'Error> (f: unit -> CloudResponce<'T, 'Error>) = 
        try f ()
        with 
            | :? System.Net.WebException as e -> failResult<'T, 'Error> e
            | :? System.ServiceModel.ProtocolException as e when (e.InnerException :? System.Net.WebException) -> 
                failResult<'T, 'Error> (e.InnerException :?> System.Net.WebException)